import util from '@/js/util/util.js';
import base from '@/js/main/attribute/base.js';

let line = {
    buffer: 2,
    x: {},
    y: {},
    element: {},
    location: { left: -10000, center: -10000, right: -10000, top: -10000, middle: -10000, bottom: -10000 },
    initialize: function() {
        this.element = {};
        this.x = {};
        this.y = {};
    },
    getLocation: function() {
        return this.location;
    },
    getElementIndex: function(array, element) {
        let index = -1;
        for (let i = 0; i < array.length; i ++) {
            if (array[i].id == element.id) {
                index = i;
                break;
            }
        }
        return index;
    },
    removeElement: function(element) {
        let item = this.element[element.id];
        if (item) {
            for (let i = 0; i < item.x.length; i ++) {
                let index = item.x[i];
                this.x[index].splice(this.getElementIndex(this.x[index], element), 1);
                if (this.x[index].length == 0) {
                    delete this.x[index];
                }
            }
            for (let i = 0; i < item.y.length; i ++) {
                let index = item.y[i];
                this.y[index].splice(this.getElementIndex(this.y[index], element), 1);
                if (this.y[index].length == 0) {
                    delete this.y[index];
                }
            }
            delete this.element[element.id];
        }
    },
    removeElementList: function(elementList) {
        for (let i = 0; i < elementList.length; i ++) {
            this.removeElement(elementList[i]);
        }
    },
    setElementList: function(elementList) {
        for (let i = 0; i < elementList.length; i ++) {
            this.setElement(elementList[i]);
        }
    },
    setElement: function(element) {
        let box = util.getElementBox(element);
        let left = box.left;
        let top = box.top;
        let right = box.right;
        let bottom = box.bottom;
        let centerX = util.toInteger((left + right) / 2);
        let centerY = util.toInteger((top + bottom) / 2);
        let item = this.element[element.id];
        if (item) {
            for (let i = 0; i < item.x.length; i ++) {
                let index = item.x[i];
                this.x[index].splice(this.getElementIndex(this.x[index], element), 1);
                if (this.x[index].length == 0) {
                    delete this.x[index];
                }
            }
            for (let i = 0; i < item.y.length; i ++) {
                let index = item.y[i];
                this.y[index].splice(this.getElementIndex(this.y[index], element), 1);
                if (this.y[index].length == 0) {
                    delete this.y[index];
                }
            }
        }
        item = { x: [], y: [] };
        for (let i = left - 0; i <= left + 0; i ++) {
            let list = this.x[i];
            if (!list) {
                list = [];
                this.x[i] = list;
            }
            list.splice(list.length, 0, element);
            item.x.splice(item.x.length, 0, i);
        }
        for (let i = centerX - 0; i <= centerX + 0; i ++) {
            let list = this.x[i];
            if (!list) {
                list = [];
                this.x[i] = list;
            }
            list.splice(list.length, 0, element);
            item.x.splice(item.x.length, 0, i);
        }
        for (let i = right - 0; i <= right + 0; i ++) {
            let list = this.x[i];
            if (!list) {
                list = [];
                this.x[i] = list;
            }
            list.splice(list.length, 0, element);
            item.x.splice(item.x.length, 0, i);
        }

        for (let i = top - 0; i <= top + 0; i ++) {
            let list = this.y[i];
            if (!list) {
                list = [];
                this.y[i] = list;
            }
            list.splice(list.length, 0, element);
            item.y.splice(item.y.length, 0, i);
        }
        for (let i = centerY - 0; i <= centerY + 0; i ++) {
            let list = this.y[i];
            if (!list) {
                list = [];
                this.y[i] = list;
            }
            list.splice(list.length, 0, element);
            item.y.splice(item.y.length, 0, i);
        }
        for (let i = bottom - 0; i <= bottom + 0; i ++) {
            let list = this.y[i];
            if (!list) {
                list = [];
                this.y[i] = list;
            }
            list.splice(list.length, 0, element);
            item.y.splice(item.y.length, 0, i);
        }
        this.element[element.id] = item;
    },
    removeLine: function() {
        this.location.left = -10000;
        this.location.center = -10000;
        this.location.right = -10000;
        this.location.top = -10000;
        this.location.middle = -10000;
        this.location.bottom = -10000;
        return this;
    },
    // 判断数组是否大于1，如果等于1且元素不等于自己返回true
    validateElementLine: function(array, element) {
        let validate = true;
        if (array.length == 1) {
            if (array[0].id == element.id) {
                validate = false;
            }
        }
        return validate;
    },
    setXLine: function(direct, element, width) {
        let box = util.getElementBox(element);
        let left = box.left;
        let center = util.toInteger((box.left + box.right) / 2);
        let right = box.right;
        let move = false;
        let offsetX = 0;
        if (direct <= 0) {
            let offsetLeft = this.getNearlyOffset(this.x, direct, element, left);
            if (offsetLeft != undefined) {
                left += offsetLeft;
                center += offsetLeft;
                right += offsetLeft;
                this.location.left = left;
                if (this.x[center] && this.validateElementLine(this.x[center], element)) {
                    this.location.center = center;
                }
                if (this.x[right] && this.validateElementLine(this.x[right], element)) {
                    this.location.right = right;
                }
                if (offsetLeft != 0) {
                    move = true;
                    offsetX = offsetLeft;
                }
            } else {
                let offsetCenter = this.getNearlyOffset(this.x, direct, element, center);
                if (offsetCenter != undefined) {
                    left += offsetCenter;
                    center += offsetCenter;
                    right += offsetCenter;
                    this.location.center = center;
                    if (this.x[left] && this.validateElementLine(this.x[left], element)) {
                        this.location.left = left;
                    }
                    if (this.x[right] && this.validateElementLine(this.x[right], element)) {
                        this.location.right = right;
                    }
                    if (offsetCenter != 0) {
                        move = true;
                        offsetX = offsetCenter;
                    }
                } else {
                    let offsetRight = this.getNearlyOffset(this.x, direct, element, right);
                    if (offsetRight != undefined) {
                        left += offsetRight;
                        center += offsetRight;
                        right += offsetRight;
                        this.location.right = right;
                        if (this.x[left] && this.validateElementLine(this.x[left], element)) {
                            this.location.left = left;
                        }
                        if (this.x[center] && this.validateElementLine(this.x[center], element)) {
                            this.location.center = center;
                        }
                        if (offsetRight != 0) {
                            move = true;
                            offsetX = offsetRight;
                        }
                    }
                }
            }
        } else {
            let offsetRight = this.getNearlyOffset(this.x, direct, element, right);
            if (offsetRight != undefined) {
                left += offsetRight;
                center += offsetRight;
                right += offsetRight;
                this.location.right = right;
                if (this.x[left] && this.validateElementLine(this.x[left], element)) {
                    this.location.left = left;
                }
                if (this.x[center] && this.validateElementLine(this.x[center], element)) {
                    this.location.center = center;
                }
                if (offsetRight != 0) {
                    move = true;
                    offsetX = offsetRight;
                }
            } else {
                let offsetCenter = this.getNearlyOffset(this.x, direct, element, center);
                if (offsetCenter != undefined) {
                    left += offsetCenter;
                    center += offsetCenter;
                    right += offsetCenter;
                    this.location.center = center;
                    if (this.x[left] && this.validateElementLine(this.x[left], element)) {
                        this.location.left = left;
                    }
                    if (this.x[right] && this.validateElementLine(this.x[right], element)) {
                        this.location.right = right;
                    }
                    if (offsetCenter != 0) {
                        move = true;
                        offsetX = offsetCenter;
                    }
                } else {
                    let offsetLeft = this.getNearlyOffset(this.x, direct, element, left);
                    if (offsetLeft != undefined) {
                        left += offsetLeft;
                        center += offsetLeft;
                        right += offsetLeft;
                        this.location.left = left;
                        if (this.x[center] && this.validateElementLine(this.x[center], element)) {
                            this.location.center = center;
                        }
                        if (this.x[right] && this.validateElementLine(this.x[right], element)) {
                            this.location.right = right;
                        }
                        if (offsetLeft != 0) {
                            move = true;
                            offsetX = offsetLeft;
                        }
                    }
                }
            }
        }
        if (move) {
            base.setLeftPixel(element, width, element.style.left.pixel + offsetX, true);
        }
        return this;
    },
    setYLine: function(direct, element, height) {
        let box = util.getElementBox(element);
        let top = box.top;
        let middle = util.toInteger((box.top + box.bottom) / 2);
        let bottom = box.bottom;
        let move = false;
        let offsetY = 0;
        if (direct <= 0) {
            let offsetTop = this.getNearlyOffset(this.y, direct, element, top);
            if (offsetTop != undefined) {
                top += offsetTop;
                middle += offsetTop;
                bottom += offsetTop;
                this.location.top = top;
                if (this.y[middle] && this.validateElementLine(this.y[middle], element)) {
                    this.location.middle = middle;
                }
                if (this.y[bottom] && this.validateElementLine(this.y[bottom], element)) {
                    this.location.bottom = bottom;
                }
                if (offsetTop != 0) {
                    move = true;
                    offsetY = offsetTop;
                }
            } else {
                let offsetMiddle = this.getNearlyOffset(this.y, direct, element, middle);
                if (offsetMiddle != undefined) {
                    top += offsetMiddle;
                    middle += offsetMiddle;
                    bottom += offsetMiddle;
                    this.location.middle = middle;
                    if (this.y[top] && this.validateElementLine(this.y[top], element)) {
                        this.location.top = top;
                    }
                    if (this.y[bottom] && this.validateElementLine(this.y[bottom], element)) {
                        this.location.bottom = bottom;
                    }
                    if (offsetMiddle != 0) {
                        move = true;
                        offsetY = offsetMiddle;
                    }
                } else {
                    let offsetBottom = this.getNearlyOffset(this.y, direct, element, bottom);
                    if (offsetBottom != undefined) {
                        top += offsetBottom;
                        middle += offsetBottom;
                        bottom += offsetBottom;
                        this.location.bottom = bottom;
                        if (this.y[top] && this.validateElementLine(this.y[top], element)) {
                            this.location.top = top;
                        }
                        if (this.y[middle] && this.validateElementLine(this.y[middle], element)) {
                            this.location.middle = middle;
                        }
                        if (offsetBottom != 0) {
                            move = true;
                            offsetY = offsetBottom;
                        }
                    }
                }
            }
        } else {
            let offsetBottom = this.getNearlyOffset(this.y, direct, element, bottom);
            if (offsetBottom != undefined) {
                top += offsetBottom;
                middle += offsetBottom;
                bottom += offsetBottom;
                this.location.bottom = bottom;
                if (this.y[top] && this.validateElementLine(this.y[top], element)) {
                    this.location.top = top;
                }
                if (this.y[middle] && this.validateElementLine(this.y[middle], element)) {
                    this.location.middle = middle;
                }
                if (offsetBottom != 0) {
                    move = true;
                    offsetY = offsetBottom;
                }
            } else {
                let offsetMiddle = this.getNearlyOffset(this.y, direct, element, middle);
                if (offsetMiddle != undefined) {
                    top += offsetMiddle;
                    middle += offsetMiddle;
                    bottom += offsetMiddle;
                    this.location.middle = middle;
                    if (this.y[top] && this.validateElementLine(this.y[top], element)) {
                        this.location.top = top;
                    }
                    if (this.y[bottom] && this.validateElementLine(this.y[bottom], element)) {
                        this.location.bottom = bottom;
                    }
                    if (offsetMiddle != 0) {
                        move = true;
                        offsetY = offsetMiddle;
                    }
                } else {
                    let offsetTop = this.getNearlyOffset(this.y, direct, element, top);
                    if (offsetTop != undefined) {
                        top += offsetTop;
                        middle += offsetTop;
                        bottom += offsetTop;
                        this.location.top = top;
                        if (this.y[middle] && this.validateElementLine(this.y[middle], element)) {
                            this.location.middle = middle;
                        }
                        if (this.y[bottom] && this.validateElementLine(this.y[bottom], element)) {
                            this.location.bottom = bottom;
                        }
                        if (offsetTop != 0) {
                            move = true;
                            offsetY = offsetTop;
                        }
                    }
                }
            }
        }
        if (move) {
            base.setTopPixel(element, height, element.style.top.pixel + offsetY, true);
        }
        return this;
    },
    getNearlyOffset: function(array, direct, element, pix) {
        let offset = undefined;
        for (let i = pix - this.buffer; i <= pix + this.buffer; i ++) {
            if (array[i]) {
                let ls = array[i];
                for (let j = 0; j < ls.length; j ++) {
                    if (ls[j].id != element.id) {
                        let distance = i - pix;
                        if (offset == undefined) {
                            offset = distance;
                        } else {
                            if (Math.abs(distance) < Math.abs(offset)) {
                                offset = distance;
                            } else if (Math.abs(distance) == Math.abs(offset)) {
                                if (direct <= 0 && distance < 0) {
                                    offset = distance;
                                } else if (direct > 0 && distance > 0) {
                                    offset = distance;
                                }
                            }
                        }
                        break;
                    }
                }
            }
            if (offset == 0) {
                break;
            }
        }
        return offset;
    }
};

export default line;